package com.naicha.wechat.wechat.face;

/**
 * @author NaiCha
 * @date 2019/5/9 16:35
 * @description TODO
 **/

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Description TODO
 * @Author 奶茶
 * Created by on 2018/12/13 14:32.
 */
public class ConcurrentPrimeFinder extends AbstractPrime {

    //线程池大小
    private final Integer poolSize;

    //被均分的任务数
    private final Integer numberOfParts;

    public ConcurrentPrimeFinder( Integer poolSize,  Integer numberOfParts) {
        this.poolSize = poolSize;
        this.numberOfParts = numberOfParts;
    }

    @Override
    public Integer countPrime( Integer number) {
        int count = 0;
        //创建线程池
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(poolSize, poolSize, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>(), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "ThreadPool_Prime");
            }
        });
        //创建线程集合
        List<Callable<Integer>> callables = new ArrayList<>();

        //将number均分为numberOfParts份 每份大小size
        int size = number/numberOfParts;
        for (int i=0;i<numberOfParts;i++){
            int start = (i*size) + 1;
            int end = (i + 1) * size;
            callables.add(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    return countPrimeInRange(start,end);
                }
            });
        }

        //执行
        try {
            List<Future<Integer>> futures = poolExecutor.invokeAll(callables, 5, TimeUnit.SECONDS);
            for (Future<Integer> integer:futures) {
                try {
                    count += integer.get();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //关闭线程池
            poolExecutor.shutdown();
        }
        return count;
    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        Integer integer = new ConcurrentPrimeFinder(4, 4).countPrime(10000000);

        long endTime = System.currentTimeMillis();
        System.out.println((endTime - startTime)/1000 + "-------" +integer);
    }
}
